package com.bangcommunity.bbframe.mlog.collector;

import com.bangcommunity.bbframe.common.base.attribute.CommonAttributeAssemble;
import com.bangcommunity.bbframe.common.base.attribute.CommonAttributeDesc;
import com.bangcommunity.bbframe.common.base.attribute.IAttributeAssemble;

/**
 * @author tanghc
 * @date 18/1/30
 */
public class StatisticBean extends StatisticBaseBean {

    public StatisticBean(String mkey) {
        super(mkey);
    }

    private static final long secondToMs = 1000;
    /**
     * 统计开始时间毫秒时间戳
     */
    private long startTimeMs = System.currentTimeMillis();
    /**
     * 最大耗时,单位毫秒
     */
    private long elapsedMsMax;
    /**
     * 最小耗时,单位毫秒
     */
    private long elapsedMsMin;
    /**
     * 耗时总和,单位毫秒
     */
    private long elapsedMsSum;
    /**
     * 平均耗时,单位毫秒
     */
    private long elapsedMsAvg;

    /**
     * 成功率,单位万分之该值
     */
    private long succRate;
    /**
     * 失败率,单位万分之该值
     */
    private long failRate;
    /**
     * 异常率,单位万分之该值
     */
    private long exceptionRate;
    /**
     * 最大并发
     */
    private long concurrentMax;
    /**
     * 最小并发
     */
    private long concurrentMin;
    /** tps */
    // private long tps;

    /**
     * vm启动毫秒时间戳
     */
    private long startTimeMsFromStartVm;

    /**
     * 从vm启动到现在的成功数
     */
    private long succFromStartVm;
    /**
     * 从vm启动到现在的失败数
     */
    private long failFromStartVm;
    /**
     * 从vm启动到现在的异常数
     */
    private long exceptionFromStartVm;
    /**
     * 从vm启动到现在的耗时总和,单位毫秒
     */
    private long elapsedMsSumFromStartVm;
    /**
     * 从vm启动到现在的平均耗时,单位毫秒
     */
    private long elapsedMsAvgFromStartVm;

    /**
     * 从vm启动到现在的成功率,单位万分之该值
     */
    private long succRateFromStartVm;
    /**
     * 从vm启动到现在的成功率,单位万分之该值
     */
    private long failRateFromStartVm;
    /**
     * 从vm启动到现在的成功率,单位万分之该值
     */
    private long exceptionRateFromStartVm;

    /**
     * 从vm启动到现在的tps
     */
    // private long tpsFromStartVm;
    public long getStartTimeMs() {
        return startTimeMs;
    }

    public void setStartTimeMs(long startTimeMs) {
        this.startTimeMs = startTimeMs;
    }

    public long getElapsedMsMax() {
        return elapsedMsMax;
    }

    public void setElapsedMsMax(long elapsedMsMax) {
        this.elapsedMsMax = elapsedMsMax;
    }

    public long getElapsedMsMin() {
        return elapsedMsMin;
    }

    public void setElapsedMsMin(long elapsedMsMin) {
        this.elapsedMsMin = elapsedMsMin;
    }

    public long getFailRate() {
        return failRate;
    }

    public void setFailRate(long failRate) {
        this.failRate = failRate;
    }

    public long getExceptionRate() {
        return exceptionRate;
    }

    public void setExceptionRate(long exceptionRate) {
        this.exceptionRate = exceptionRate;
    }

    public long getConcurrentMax() {
        return concurrentMax;
    }

    public void setConcurrentMax(long concurrentMax) {
        this.concurrentMax = concurrentMax;
    }

    public long getConcurrentMin() {
        return concurrentMin;
    }

    public void setConcurrentMin(long concurrentMin) {
        this.concurrentMin = concurrentMin;
    }

    public long getSuccRate() {
        return succRate;
    }

    public void setSuccRate(long succRate) {
        this.succRate = succRate;
    }

    public long getSuccFromStartVm() {
        return succFromStartVm;
    }

    public void setSuccFromStartVm(long succFromStartVm) {
        this.succFromStartVm = succFromStartVm;
    }

    public long getFailFromStartVm() {
        return failFromStartVm;
    }

    public void setFailFromStartVm(long failFromStartVm) {
        this.failFromStartVm = failFromStartVm;
    }

    public long getExceptionFromStartVm() {
        return exceptionFromStartVm;
    }

    public void setExceptionFromStartVm(long exceptionFromStartVm) {
        this.exceptionFromStartVm = exceptionFromStartVm;
    }

    public long getSuccRateFromStartVm() {
        return succRateFromStartVm;
    }

    public void setSuccRateFromStartVm(long succRateFromStartVm) {
        this.succRateFromStartVm = succRateFromStartVm;
    }

    public long getFailRateFromStartVm() {
        return failRateFromStartVm;
    }

    public void setFailRateFromStartVm(long failRateFromStartVm) {
        this.failRateFromStartVm = failRateFromStartVm;
    }

    public long getExceptionRateFromStartVm() {
        return exceptionRateFromStartVm;
    }

    public void setExceptionRateFromStartVm(long exceptionRateFromStartVm) {
        this.exceptionRateFromStartVm = exceptionRateFromStartVm;
    }

    public long getElapsedMsSum() {
        return elapsedMsSum;
    }

    public void setElapsedMsSum(long elapsedMsSum) {
        this.elapsedMsSum = elapsedMsSum;
    }

    public long getTransactionsFromStartVm() {
        return this.succFromStartVm + this.failFromStartVm + this.exceptionFromStartVm;
    }

    public long getStartTimeMsFromStartVm() {
        return startTimeMsFromStartVm;
    }

    public void setStartTimeMsFromStartVm(long startTimeMsFromStartVm) {
        this.startTimeMsFromStartVm = startTimeMsFromStartVm;
    }

    public long getElapsedMsAvg() {
        return elapsedMsAvg;
    }

    public void setElapsedMsAvg(long elapsedMsAvg) {
        this.elapsedMsAvg = elapsedMsAvg;
    }

    public long getElapsedMsSumFromStartVm() {
        return elapsedMsSumFromStartVm;
    }

    public void setElapsedMsSumFromStartVm(long elapsedMsSumFromStartVm) {
        this.elapsedMsSumFromStartVm = elapsedMsSumFromStartVm;
    }

    public long getElapsedMsAvgFromStartVm() {
        return elapsedMsAvgFromStartVm;
    }

    public void setElapsedMsAvgFromStartVm(long elapsedMsAvgFromStartVm) {
        this.elapsedMsAvgFromStartVm = elapsedMsAvgFromStartVm;
    }

    public long calculateRate(long count, long totalCount) {
        if (totalCount > 0 && count > 0) {
            return rateForTenThousand(count, totalCount);
        }
        return 0;
    }

    public void calculateWithTransactions() {
        long ts = this.getTransactions();
        if (ts <= 0) {
            this.setSuccRate(rateForTenThousand(1, 1));
        } else {
            this.setSuccRate(calculateRate(this.getSucc(), ts));
            this.setFailRate(calculateRate(this.getFail(), ts));
            this.setExceptionRate(calculateRate(this.getException(), ts));
            this.setElapsedMsAvg(this.getElapsedMsSum() / ts);
        }
        // long l = System.currentTimeMillis() - this.getStartTimeMs();
        // if(l > 0){
        // this.tps = (ts * secondToMs) / l;
        // }
    }

    public void calculateFromStartVmWithTransactions() {
        long ts = this.getTransactionsFromStartVm();
        if (ts <= 0) {
            this.setSuccRateFromStartVm(rateForTenThousand(1, 1));
        } else {
            this.setSuccRateFromStartVm(calculateRate(this.getSuccFromStartVm(), ts));
            this.setFailRateFromStartVm(calculateRate(this.getFailFromStartVm(), ts));
            this.setExceptionRateFromStartVm(calculateRate(this.getExceptionFromStartVm(), ts));
            this.setElapsedMsAvgFromStartVm(this.getElapsedMsSumFromStartVm() / ts);
        }
        // long l = System.currentTimeMillis() - this.getStartTimeMsFromStartVm();
        // if(l > 0){
        // this.tpsFromStartVm = (ts * secondToMs) / l;
        // }
    }

    private long rateForTenThousand(long value, long all) {
        return (value * 10000) / all;
    }

    public void initStatistisFromStartVm(StatisticBean lastStatistic) {
        if (null != lastStatistic) {
            this.setSuccFromStartVm(lastStatistic.getSuccFromStartVm());
            this.setFailFromStartVm(lastStatistic.getFailFromStartVm());
            this.setExceptionFromStartVm(lastStatistic.getExceptionFromStartVm());
            this.setStartTimeMsFromStartVm(lastStatistic.getStartTimeMsFromStartVm());
            this.setElapsedMsSumFromStartVm(lastStatistic.getElapsedMsSumFromStartVm());
        }
    }

    public void collectFirst(StatisticBaseBean changes) {
        this.setMkey(changes.getMkey());

        this.setStartTimeMsFromStartVm(System.currentTimeMillis());

        this.setConcurrent(changes.getConcurrent());
        this.setConcurrentMax(changes.getConcurrent());
        this.setConcurrentMin(changes.getConcurrent());

        this.setElapsedMs(changes.getElapsedMs());
        this.setElapsedMsMax(changes.getElapsedMs());
        this.setElapsedMsMin(changes.getElapsedMs());
        this.setElapsedMsSum(changes.getElapsedMs());
        this.setElapsedMsSumFromStartVm(changes.getElapsedMs());

        this.setSucc(changes.getSucc());
        this.setFail(changes.getFail());
        this.setException(changes.getException());
        this.setSuccFromStartVm(changes.getSucc());
        this.setFailFromStartVm(changes.getFail());
        this.setExceptionFromStartVm(changes.getException());

    }

    public void collect(StatisticBean current, StatisticBaseBean changes) {
        this.setConcurrent((changes.getConcurrent() + current.getConcurrent()) / 2);
        this.setConcurrentMax(Math.max(changes.getConcurrent(), current.getConcurrentMax()));
        this.setConcurrentMin(Math.min(changes.getConcurrent(), current.getConcurrentMin()));

        this.setElapsedMs((changes.getElapsedMs() + current.getElapsedMs()) / 2);
        this.setElapsedMsMax(Math.max(changes.getElapsedMs(), current.getElapsedMsMax()));
        this.setElapsedMsMin(Math.min(changes.getElapsedMs(), current.getElapsedMsMin()));
        this.setElapsedMsSum(changes.getElapsedMs() + current.getElapsedMsSum());
        this.setElapsedMsSumFromStartVm(changes.getElapsedMs() + current.getElapsedMsSumFromStartVm());

        this.setSucc(changes.getSucc() + current.getSucc());
        this.setFail(changes.getFail() + current.getFail());
        this.setException(changes.getException() + current.getException());
        this.setSuccFromStartVm(changes.getSucc() + current.getSuccFromStartVm());
        this.setFailFromStartVm(changes.getFail() + current.getFailFromStartVm());
        this.setExceptionFromStartVm(changes.getException() + current.getExceptionFromStartVm());
    }

    public void calculateAll() {
        calculateWithTransactions();
        calculateFromStartVmWithTransactions();
    }

    // public StatisticBean copy() {
    // StatisticBean copy = new StatisticBean();
    // copy.setStartTimeMsFromStartVm(this.getStartTimeMsFromStartVm());
    // copy.setStartTimeMs(this.getStartTimeMs());
    //
    // copy.setConcurrent(this.getConcurrent());
    // copy.setConcurrentMax(this.getConcurrentMax());
    // copy.setConcurrentMin(this.getConcurrentMin());
    //
    // copy.setElapsedMs(this.getElapsedMs());
    // copy.setElapsedMsMax(this.getElapsedMsMax());
    // copy.setElapsedMsMin(this.getElapsedMsMin());
    // copy.setElapsedMsSum(this.getElapsedMsSum());
    // copy.setElapsedMsSumFromStartVm(this.getElapsedMsSumFromStartVm());
    //
    // copy.setSucc(this.getSucc());
    // copy.setFail(this.getFail());
    // copy.setException(this.getException());
    // copy.setSuccFromStartVm(this.getSuccFromStartVm());
    // copy.setFailFromStartVm(this.getFailFromStartVm());
    // copy.setExceptionFromStartVm(this.getExceptionFromStartVm());
    // return copy;
    // }

    // public String toLogRecordString() {
    // StatisticBean copy = this.copy();
    // copy.calculateAll();
    //
    // return new StringBuilder(256)
    // // 当前毫秒时间戳
    // .append(System.currentTimeMillis()).append(" ")
    // // 平均响应时间 毫秒
    // .append(copy.getElapsedMsAvg()).append(" ")
    // // 从vm启动到现在的平均响应时间 毫秒
    // .append(copy.getElapsedMsAvgFromStartVm()).append(" ")
    // // 响应时间最大 毫秒
    // .append(copy.getElapsedMsMax()).append(" ")
    // // 响应时间最小 毫秒
    // .append(copy.getElapsedMsMin()).append(" ")
    // //并发
    // .append(copy.getConcurrent()).append(" ")
    // //并发最大
    // .append(copy.getConcurrentMax()).append(" ")
    // //并发最小
    // .append(copy.getConcurrentMin()).append(" ")
    // //成功
    // .append(copy.getSucc()).append(" ")
    // //失败
    // .append(copy.getFail()).append(" ")
    // //异常
    // .append(copy.getException()).append(" ")
    // //成功率
    // .append(copy.getSuccRate()).append(" ")
    // //失败率
    // .append(copy.getFailRate()).append(" ")
    // //异常率
    // .append(copy.getExceptionRate()).append(" ")
    // //从vm启动到现在的成功率
    // .append(copy.getSuccRateFromStartVm()).append(" ")
    // //从vm启动到现在的失败率
    // .append(copy.getFailRateFromStartVm()).append(" ")
    // //从vm启动到现在的异常率
    // .append(copy.getExceptionRateFromStartVm()).append(" ")
    //// //tps
    //// .append(copy.getTps()).append(" ")
    //// //从vm启动到现在的tps
    //// .append(copy.getTpsFromStartVm()).append(" ")
    // //统计区间内响应的请求数
    // .append(copy.getTransactions()).append(" ")
    // //从vm启动到现在响应的请求数
    // .append(copy.getTransactionsFromStartVm()).append(" ")
    // .toString();
    // }
    // public String toLogRecordString() {
    // this.calculateAll();
    //
    // return new StringBuilder(256)
    // // 当前毫秒时间戳
    // .append(System.currentTimeMillis()).append(" ")
    // // 平均响应时间 毫秒
    // .append(this.getElapsedMsAvg()).append(" ")
    // // 从vm启动到现在的平均响应时间 毫秒
    // .append(this.getElapsedMsAvgFromStartVm()).append(" ")
    // // 响应时间最大 毫秒
    // .append(this.getElapsedMsMax()).append(" ")
    // // 响应时间最小 毫秒
    // .append(this.getElapsedMsMin()).append(" ")
    // //并发
    // .append(this.getConcurrent()).append(" ")
    // //并发最大
    // .append(this.getConcurrentMax()).append(" ")
    // //并发最小
    // .append(this.getConcurrentMin()).append(" ")
    // //成功
    // .append(this.getSucc()).append(" ")
    // //失败
    // .append(this.getFail()).append(" ")
    // //异常
    // .append(this.getException()).append(" ")
    // //成功率
    // .append(this.getSuccRate()).append(" ")
    // //失败率
    // .append(this.getFailRate()).append(" ")
    // //异常率
    // .append(this.getExceptionRate()).append(" ")
    // //从vm启动到现在的成功率
    // .append(this.getSuccRateFromStartVm()).append(" ")
    // //从vm启动到现在的失败率
    // .append(this.getFailRateFromStartVm()).append(" ")
    // //从vm启动到现在的异常率
    // .append(this.getExceptionRateFromStartVm()).append(" ")
    //// //tps
    //// .append(this.getTps()).append(" ")
    //// //从vm启动到现在的tps
    //// .append(this.getTpsFromStartVm()).append(" ")
    // //统计区间内响应的请求数
    // .append(this.getTransactions()).append(" ")
    // //从vm启动到现在响应的请求数
    // .append(this.getTransactionsFromStartVm()).append(" ")
    // .toString();
    // }

    public IAttributeAssemble toAttributeAssemble() {
        this.calculateAll();
        //todo
        return new CommonAttributeAssemble().add(new CommonAttributeDesc("productCode", this.productCode, true))
                .add(new CommonAttributeDesc("productCode", this.productCode, true))
                .add(new CommonAttributeDesc("appCode", this.productCode + "_" + this.appCode, true))
                .add(new CommonAttributeDesc("methodCode", this.getMkey(), true))
                .add(new CommonAttributeDesc("logType", "mlog", true))
                .add(new CommonAttributeDesc("systemCurrentTimeMillis", System.currentTimeMillis()))
                .add(new CommonAttributeDesc("ElapsedMsAvg", this.getElapsedMsAvg()))
                .add(new CommonAttributeDesc("ElapsedMsAvgFromStartVm", this.getElapsedMsAvgFromStartVm()))
                .add(new CommonAttributeDesc("ElapsedMsMax", this.getElapsedMsMax()))
                .add(new CommonAttributeDesc("ElapsedMsMin", this.getElapsedMsMin()))
                .add(new CommonAttributeDesc("Concurrent", this.getConcurrent()))
                .add(new CommonAttributeDesc("ConcurrentMax", this.getConcurrentMax()))
                .add(new CommonAttributeDesc("ConcurrentMin", this.getConcurrentMin()))
                .add(new CommonAttributeDesc("Succ", this.getSucc()))
                .add(new CommonAttributeDesc("Fail", this.getFail()))
                .add(new CommonAttributeDesc("Exception", this.getException()))
                .add(new CommonAttributeDesc("SuccRate", this.getSuccRate()))
                .add(new CommonAttributeDesc("FailRate", this.getFailRate()))
                .add(new CommonAttributeDesc("ExceptionRate", this.getExceptionRate()))
                .add(new CommonAttributeDesc("SuccRateFromStartVm", this.getSuccRateFromStartVm()))
                .add(new CommonAttributeDesc("FailRateFromStartVm", this.getFailRateFromStartVm()))
                .add(new CommonAttributeDesc("ExceptionRateFromStartVm", this.getExceptionRateFromStartVm()))
                .add(new CommonAttributeDesc("Transactions", this.getTransactions()))
                .add(new CommonAttributeDesc("TransactionsFromStartVm", this.getTransactionsFromStartVm()));
    }

    // public String toLogRecordJsonString() {
    // this.calculateAll();
    //
    // return new StringBuilder(512)
    // .append("{")
    //
    // .append("\"productCode\"").append(":").append("\"").append(this.productCode).append("\"").append(",")
    // .append("\"appCode\"").append(":").append("\"").append(this.productCode + "_" +
    // this.appCode).append("\"").append(",")
    // .append("\"methodCode\"").append(":").append("\"").append(this.getMkey()).append("\"").append(",")
    // .append("\"logType\"").append(":").append("\"").append("mlog").append("\"").append(",")
    //
    // // 当前毫秒时间戳
    // .append("\"systemCurrentTimeMillis\"").append(":").append(System.currentTimeMillis()).append(",")
    // // 平均响应时间 毫秒
    // .append("\"ElapsedMsAvg\"").append(":").append(this.getElapsedMsAvg()).append(",")
    // // 从vm启动到现在的平均响应时间 毫秒
    // .append("\"ElapsedMsAvgFromStartVm\"").append(":").append(this.getElapsedMsAvgFromStartVm()).append(",")
    // // 响应时间最大 毫秒
    // .append("\"ElapsedMsMax\"").append(":").append(this.getElapsedMsMax()).append(",")
    // // 响应时间最小 毫秒
    // .append("\"ElapsedMsMin\"").append(":").append(this.getElapsedMsMin()).append(",")
    // //并发
    // .append("\"Concurrent\"").append(":").append(this.getConcurrent()).append(",")
    // //并发最大
    // .append("\"ConcurrentMax\"").append(":").append(this.getConcurrentMax()).append(",")
    // //并发最小
    // .append("\"ConcurrentMin\"").append(":").append(this.getConcurrentMin()).append(",")
    // //成功
    // .append("\"Succ\"").append(":").append(this.getSucc()).append(",")
    // //失败
    // .append("\"Fail\"").append(":").append(this.getFail()).append(",")
    // //异常
    // .append("\"Exception\"").append(":").append(this.getException()).append(",")
    // //成功率
    // .append("\"SuccRate\"").append(":").append(this.getSuccRate()).append(",")
    // //失败率
    // .append("\"FailRate\"").append(":").append(this.getFailRate()).append(",")
    // //异常率
    // .append("\"ExceptionRate\"").append(":").append(this.getExceptionRate()).append(",")
    // //从vm启动到现在的成功率
    // .append("\"SuccRateFromStartVm\"").append(":").append(this.getSuccRateFromStartVm()).append(",")
    // //从vm启动到现在的失败率
    // .append("\"FailRateFromStartVm\"").append(":").append(this.getFailRateFromStartVm()).append(",")
    // //从vm启动到现在的异常率
    // .append("\"ExceptionRateFromStartVm\"").append(":").append(this.getExceptionRateFromStartVm()).append(",")
    //// //tps
    //// .append(this.getTps()).append(",")
    //// //从vm启动到现在的tps
    //// .append(this.getTpsFromStartVm()).append(",")
    // //统计区间内响应的请求数
    // .append("\"Transactions\"").append(":").append(this.getTransactions()).append(",")
    // //从vm启动到现在响应的请求数
    // .append("\"TransactionsFromStartVm\"").append(":").append(this.getTransactionsFromStartVm())
    //
    //
    // .append("}")
    // .toString();
    // }

}
